package weiyao.xinxidasai.Utils;

import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;

public class FileTypes {

    private static final Map<FileTypeName, String[]> FILE_TYPE_MAP = new HashMap<>();
    private static final int BYTES_TO_READ = 16; // 读取16字节用于文件头检测

    static {
        initAllFileType();
    }

    private FileTypes() {
    }

    public enum FileTypeName {
        // 图片格式
        JPG("jpg"),
        PNG("png"),
        GIF("gif"),
        BMP("bmp"),
        TIFF("tiff"),
        WEBP("webp"),
        ICO("ico"),
        PSD("psd"),

        // 文档格式
        PDF("pdf"),
        DOC("doc"),
        DOCX("docx"),
        XLS("xls"),
        XLSX("xlsx"),
        PPT("ppt"),
        PPTX("pptx"),
        TXT("txt"),
        RTF("rtf"),

        // 压缩文件
        ZIP("zip"),
        RAR("rar"),
        GZIP("gz"),
        TAR("tar"),
        SEVEN_ZIP("7z"),

        // 音视频格式
        MP3("mp3"),
        WAV("wav"),
        FLAC("flac"),
        MP4("mp4"),
        AVI("avi"),
        MOV("mov"),
        WMV("wmv"),
        FLV("flv"),

        // 可执行文件
        EXE("exe"),
        DLL("dll"),

        // 字体文件
        TTF("ttf"),
        OTF("otf"),
        WOFF("woff"),
        WOFF2("woff2"),

        // 其他
        ISO("iso"),
        SQLITE("db");

        private final String extension;

        FileTypeName(String extension) {
            this.extension = extension;
        }

        public String getExtension() {
            return extension;
        }
    }

    public static Boolean checkType(FileTypeName fileTypeName, File file) {
        try (FileInputStream fileInputStream = new FileInputStream(file)) {
            byte[] bytes = new byte[BYTES_TO_READ];
            int read = fileInputStream.read(bytes, 0, bytes.length);
            if (read == -1) return false;

            String fileCode = bytesToHexString(bytes).toUpperCase();
            String[] patterns = FILE_TYPE_MAP.get(fileTypeName);
            if (patterns == null) return false;

            for (String pattern : patterns) {
                if (fileCode.startsWith(pattern.toUpperCase())) {
                    return true;
                }
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
        return false;
    }

    public static String getType(File file) {
        try (FileInputStream is = new FileInputStream(file)) {
            byte[] bytes = new byte[BYTES_TO_READ];
            int read = is.read(bytes, 0, bytes.length);
            if (read == -1) return "-1";

            String fileCode = bytesToHexString(bytes).toUpperCase();
            for (Map.Entry<FileTypeName, String[]> entry : FILE_TYPE_MAP.entrySet()) {
                for (String pattern : entry.getValue()) {
                    if (fileCode.startsWith(pattern.toUpperCase())) {
                        return entry.getKey().getExtension();
                    }
                }
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
        return "-1";
    }

    private static void initAllFileType() {
        // 图片类型
        FILE_TYPE_MAP.put(FileTypeName.JPG, new String[]{"FFD8FF"});
        FILE_TYPE_MAP.put(FileTypeName.PNG, new String[]{"89504E47"});
        FILE_TYPE_MAP.put(FileTypeName.GIF, new String[]{"47494638"});
        FILE_TYPE_MAP.put(FileTypeName.BMP, new String[]{"424D"});
        FILE_TYPE_MAP.put(FileTypeName.TIFF, new String[]{"49492A00", "4D4D002A"});
        FILE_TYPE_MAP.put(FileTypeName.WEBP, new String[]{"52494646????57454250"});
        FILE_TYPE_MAP.put(FileTypeName.ICO, new String[]{"00000100"});
        FILE_TYPE_MAP.put(FileTypeName.PSD, new String[]{"38425053"});

        // 文档类型
        FILE_TYPE_MAP.put(FileTypeName.PDF, new String[]{"25504446"});
        FILE_TYPE_MAP.put(FileTypeName.DOC, new String[]{"D0CF11E0"});
        FILE_TYPE_MAP.put(FileTypeName.DOCX, new String[]{"504B030414000600"});
        FILE_TYPE_MAP.put(FileTypeName.XLS, new String[]{"D0CF11E0"});
        FILE_TYPE_MAP.put(FileTypeName.XLSX, new String[]{"504B030414000600"});
        FILE_TYPE_MAP.put(FileTypeName.PPT, new String[]{"D0CF11E0"});
        FILE_TYPE_MAP.put(FileTypeName.PPTX, new String[]{"504B030414000600"});
        FILE_TYPE_MAP.put(FileTypeName.TXT, new String[]{"EFBBBF", "FFFE", "FEFF", "0000"});
        FILE_TYPE_MAP.put(FileTypeName.RTF, new String[]{"7B5C727466"});

        // 压缩文件
        FILE_TYPE_MAP.put(FileTypeName.ZIP, new String[]{"504B0304", "504B0506", "504B0708"});
        FILE_TYPE_MAP.put(FileTypeName.RAR, new String[]{"526172211A0700", "526172211A070100"});
        FILE_TYPE_MAP.put(FileTypeName.GZIP, new String[]{"1F8B08"});
        FILE_TYPE_MAP.put(FileTypeName.TAR, new String[]{"7573746172"});
        FILE_TYPE_MAP.put(FileTypeName.SEVEN_ZIP, new String[]{"377ABCAF271C"});

        // 音视频
        FILE_TYPE_MAP.put(FileTypeName.MP3, new String[]{"494433", "FFFB", "FFF3"});
        FILE_TYPE_MAP.put(FileTypeName.WAV, new String[]{"52494646????57415645"});
        FILE_TYPE_MAP.put(FileTypeName.FLAC, new String[]{"664C6143"});
        FILE_TYPE_MAP.put(FileTypeName.MP4, new String[]{"000000????66747970", "0000001866747970"});
        FILE_TYPE_MAP.put(FileTypeName.AVI, new String[]{"52494646????41564920"});
        FILE_TYPE_MAP.put(FileTypeName.MOV, new String[]{"000000????66747970"});
        FILE_TYPE_MAP.put(FileTypeName.WMV, new String[]{"3026B2758E66CF11"});
        FILE_TYPE_MAP.put(FileTypeName.FLV, new String[]{"464C5601"});

        // 可执行文件
        FILE_TYPE_MAP.put(FileTypeName.EXE, new String[]{"4D5A"});
        FILE_TYPE_MAP.put(FileTypeName.DLL, new String[]{"4D5A"});

        // 字体文件
        FILE_TYPE_MAP.put(FileTypeName.TTF, new String[]{"00010000", "74727565"});
        FILE_TYPE_MAP.put(FileTypeName.OTF, new String[]{"4F54544F"});
        FILE_TYPE_MAP.put(FileTypeName.WOFF, new String[]{"774F4646"});
        FILE_TYPE_MAP.put(FileTypeName.WOFF2, new String[]{"774F4632"});

        // 其他
        FILE_TYPE_MAP.put(FileTypeName.ISO, new String[]{"43443030"});
        FILE_TYPE_MAP.put(FileTypeName.SQLITE, new String[]{"53514C697465"});
    }

    private static String bytesToHexString(byte[] bytes) {
        StringBuilder stringBuilder = new StringBuilder();
        for (byte b : bytes) {
            int v = b & 0xFF;
            String hv = Integer.toHexString(v);
            if (hv.length() < 2) {
                stringBuilder.append(0);
            }
            stringBuilder.append(hv);
        }
        return stringBuilder.toString();
    }




}